#include "app.h"
#include "utils.h"
#include "cli.h"

static int prompt_ProcessCommand(void);
static int prompt_Beep(int argc, portCHAR **argv);
static int prompt_Relay(int argc, portCHAR **argv);
static int prompt_ClearTicks(int argc, portCHAR **argv);
static int prompt_eeDump(int argc, portCHAR **argv);
static int prompt_eeTest(int argc, portCHAR **argv);
static int prompt_SetDate (int argc, portCHAR **argv);
static int prompt_SetTime (int argc, portCHAR **argv);
static int prompt_STS(int argc, portCHAR **argv);

// ###############################################################################################
// LISTA DOS COMANDOS A SER CHAMADOS PELO CLI

static const tCLI cli_list [] = {
	{ "help",
  			0,  0,
  			CMD_TYPE_FUNCTION, { cli_Help },
  			"Displays this help list", NULL },

	{ "beep",
			1,  1,
  			CMD_TYPE_FUNCTION,  { prompt_Beep },
  			"Play beep sound", "beep <mode: 0(off) at 6>" },

	{ "beep",
			1,  1,
  			CMD_TYPE_FUNCTION,  { prompt_Beep },
  			"Play beep sound", "beep <mode: 0(off) at 6>" },

	{ "relay",
  			2,  3,
  			CMD_TYPE_FUNCTION,  { prompt_Relay },
  			"Turn on or off determined relay", "realy <1/2> <on/off> <timeout in secs (OPT)>" },

	{ "ee_dump",
  			2,  2, CMD_TYPE_FUNCTION,  	{ prompt_eeDump },
  			"Dump eeprom",
  			"ee_dump <addr> <size>" },

	{ "ee_test",
  			0,  0, CMD_TYPE_FUNCTION,  	{ prompt_eeTest },
  			"Test eeprom",
  			"ee_test" },

	{ "dump",
  			2,  2, CMD_TYPE_FUNCTION,  	{ prompt_Dump },
  			"Dump memory",
  			"dump <addr> <size>" },

	{ "set_date",
  			4,  4, CMD_TYPE_FUNCTION,  	{ prompt_SetDate },
 			"Set Date",
  			"set_date <year> <mon> <day> <week 1(sun) 2(mon) ... 7(sat)>" },

	{ "set_time",
  			3,  3, CMD_TYPE_FUNCTION,  	{ prompt_SetTime },
  			"Set time",
  			"set_time <hour> <min> <sec>" },

	{ "clear_ticks",
			0,  0,
  			CMD_TYPE_FUNCTION,  { prompt_ClearTicks },
  			"Clear counter ticks system", NULL },

	{ "sts",
  			0,  0,
  			CMD_TYPE_FUNCTION,  { prompt_STS },
  			"Shows all status of the ", 	NULL },

	{ NULL, 0,  0, CMD_TYPE_FUNCTION,  	{ NULL },
			NULL,
			NULL },
};

void prompt_Process(void) {
	static int resuslt;
	resuslt = prompt_ProcessCommand();
	switch (resuslt) {
	case errCLI_EXED_ARGS:
		lprintf("System error"CMD_TERMINATOR);
		break;
	case errCLI_CMD_NOT_FOUND:
		lprintf("Unknown command"CMD_TERMINATOR);
    	break;
    case pdFAIL:
    	lprintf("Error in executing the command"CMD_TERMINATOR);
    	break;
    }
}

static int result_prompt;
static u8 buffer_prompt[CLI_CMD_BUFFER_SIZE];
static portCHAR *argv_prompt [CLI_N_ARGS];
static int argc_prompt;

static int prompt_ProcessCommand(void) {
	// CAPTURA COMANDOS DO TERMINAL. SE TECLOU ENTER A FUNÇÃO RETORNA COM A QUANTIDADE DE CHAR DO COMANDO
	result_prompt = cli_GetLine (buffer_prompt, sizeof (buffer_prompt), PROMPT); // Chamo o console para entrada de comandos

	// CHECA FOI ENTRADO COM O COMANDO
	if (result_prompt) {	// checa se há entrada de comandos
   		if (cli_ArgsParse ((char *) buffer_prompt, argv_prompt, sizeof (argv_prompt), &argc_prompt) == errCLI_EXED_ARGS) // Captura os endereços iniciais de cada argumento, contidos no comando, e grava nas posições do argv
   			result_prompt = errCLI_EXED_ARGS;
   		else if (argv_prompt[0])
   			result_prompt = cli_ArgsDispatch(cli_list, argc_prompt, &argv_prompt[0]);							// Executa a função referente ao comando digitado
  	} else result_prompt = pdPASS;

	return result_prompt;
}

static int prompt_Beep(int argc __attribute__ ((unused)), portCHAR **argv) {
	long p1;
	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	beep_Play(p1);
	return pdPASS;
}

static int prompt_Relay(int argc __attribute__ ((unused)), portCHAR **argv ) {
	long p1=0, p2=0, p3=0;

	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	if (strcmp(argv[1], "on") == 0) p2=pdON; else p2=pdOFF;
	if (argc > 2) { if (!xatoi(&argv[2], &p3)) return pdFAIL; }

	int ret = relay_Set(p1-1, p2, p3);

	if (ret == errDEVICE_NOT_FOUND)
		lprintf("ERROR: relay must be 1 or 2"CMD_TERMINATOR);

	return pdPASS;
}

static int prompt_ClearTicks(int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused))) {
	control.ticks = 0;
	return pdPASS;
}

static int prompt_eeDump(int argc __attribute__ ((unused)), portCHAR **argv ) {
	long p1, p2;

	if (!xatoi(&argv[0], &p1)) return pdFAIL;
	if (!xatoi(&argv[1], &p2)) return pdFAIL;

	if (p2 < 1) p2 = 256;
	if (p1 < 0) p1 = 0;

	ee25xx_dump(p1, p2);
	return pdPASS;
}

static int prompt_eeTest(int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)) ) {
	#define eeTOTAL 4*1024

	int x, ret;

	lprintf("Writing eeprom ..."CMD_TERMINATOR);
	for (x=0;x<eeTOTAL;x++) {
		if ((x%100)==0) lprintf(".");
		ee25xx_WriteByte(x, (u8)x);
	}
	lprintf(CMD_TERMINATOR"Reading eeprom ..."CMD_TERMINATOR);
	for (x=0;x<eeTOTAL;x++) {
		if ((x%100)==0) lprintf(".");
		ret = ee25xx_ReadByte(x);
		if (ret != (u8)x) lprintf("Error address: 0x%x value corret: 0x%x value read: 0x%x"CMD_TERMINATOR, x, (u8)x, ret);
	}

	lprintf(CMD_TERMINATOR);
	return pdPASS;
}

// set_date [<year> <mon> <mday> <week>]
// OBS: não colocar 0 a esquerda do número
int prompt_SetDate (int argc __attribute__ ((unused)), portCHAR **argv) {
	long p1;

	if (!xatoi(&argv[0], &p1))	{ return pdPASS; }
	control.rtc.year = (u32)p1;
	if (!xatoi(&argv[1], &p1))	{ return pdPASS; }
	control.rtc.month = (u8)p1;
	if (!xatoi(&argv[2], &p1))	{ return pdPASS; }
	control.rtc.mday = (u8)p1;
	if (!xatoi(&argv[3], &p1))	{ return pdPASS; }
	control.rtc.wday = (u32)p1-1;

	rtc_SetTime(&control.rtc);

	return pdPASS;
}

// set_time [<hour> <min> <sec>]
 // OBS: não colocar 0 a esquerda do número
int prompt_SetTime (int argc __attribute__ ((unused)), portCHAR **argv) {
	long p1;

	if (!xatoi(&argv[0], &p1))	{ return pdPASS; }
	control.rtc.hour = (u8)p1;
	if (!xatoi(&argv[1], &p1))	{ return pdPASS; }
	control.rtc.min = (u8)p1;
	if (!xatoi(&argv[2], &p1))	{ return pdPASS; }
	control.rtc.sec = (u8)p1;

	rtc_SetTime(&control.rtc);

	return pdPASS;
}

static int prompt_STS(int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused))) {
	lprintf(CMD_TERMINATOR);
	lprintf(CMD_TERMINATOR);
	lprintf("SYSTEM"CMD_TERMINATOR);
	lprintf("    "PROGAM_NAME);
	lprintf("    ucLibc version "__VERSION CMD_TERMINATOR);
	lprintf("    count TICKS: %u"CMD_TERMINATOR, control.ticks);
	lprintf("    key pressing: %u"CMD_TERMINATOR, control.key);
	lprintf(CMD_TERMINATOR);

	lprintf(CMD_TERMINATOR);
	lprintf("DATE/HOUR"CMD_TERMINATOR);
	lprintf("    Date: %04u/%02u/%02u"CMD_TERMINATOR, control.rtc.year, control.rtc.month, control.rtc.mday);
	lprintf("    Hour: %02u:%02u:%02u"CMD_TERMINATOR, control.rtc.hour, control.rtc.min, control.rtc.sec);
	lprintf("    Day week: ");

	switch(control.rtc.wday) {
	case 0: lprintf("Sunday"); break;
	case 1: lprintf("Monday"); break;
	case 2: lprintf("Tuesday"); break;
	case 3: lprintf("Wednesday"); break;
	case 4: lprintf("Thursday"); break;
	case 5: lprintf("Friday"); break;
	default:lprintf("Saturday"); break;
	}

	lprintf(CMD_TERMINATOR);
	lprintf("    AUTO CALIBRATION: %s"CMD_TERMINATOR, (CCR&0x10)?"OFF":"ON");
	lprintf("    CALIBRATION: %d"CMD_TERMINATOR, CALIBRATION);
	lprintf("        CCR: 0x%x"CMD_TERMINATOR, CCR);
	lprintf("        CALDIR: %d"CMD_TERMINATOR, (CALIBRATION&0x20000)>>17);
	lprintf("        CALVAL: %d"CMD_TERMINATOR, (CALIBRATION&0x1FFFF) );

	return pdPASS;
}
